/*
 Trabajo Practico 3 Ejercicio 2
 * Cliente
 Segunda Entrega

 - Integrantes:
		- Barrera, Lourdes				DNI: 33306634
		- Martinez, Guillermo			DNI: 34510461
		- Reyes, Leandro				DNI: 34213699
		- Rodriguez, Lucas				DNI: 34265017
*/

#include "defines.h"

// Variables Semáforo
sem_t* mutex_atencion;			// Server puede procesar
sem_t* mutex_mensaje;				// Hay mensaje para procesar
sem_t* mutex_mem;						// Mutex memoria compartida
sem_t* mutex_respuesta;			// Cliente puede leer respuesta
sem_t* mutex_inicio;				// Cliente puede iniciar

// Memoria compartida
char *mcompartida = NULL;
int id_mem = 0;

typedef struct
{
	int moneda;
	int cotizacion;
	int cant_comprada;
}t_ingreso;

int verificar_moneda(int);
void abrir_semaforos();
void cerrar_semaforos();
void handler(int);

int main()
{
	key_t sh_key;
	int flag_fin=0;
	char buf[10],envio[BUFFER];
	t_ingreso ingreso;
	
	// Generar clave
	sh_key = ftok("/bin/ls",10);
	if(sh_key == -1)
		error("Error Key\n");

	// Generar memoria compartida
	id_mem = shmget(sh_key,sizeof(char *),0777 | IPC_CREAT);
	if(id_mem == -1)
		error("Error memoria compartida\n");
	
	// Generar semáforos
	abrir_semaforos();

	// Attach memoria
	mcompartida = (char *)shmat(id_mem,NULL,0);
	if(mcompartida == NULL)
		error("No hay memoria compartida disponible\n");
		
	// Manejador señal finalización
	signal(SIGINT,handler);
	signal(SIGTERM,handler);
		
	// Mando PID de inicio
	sprintf(envio,"%d",getpid());
	P(mutex_inicio);
	P(mutex_mem);
	strcpy(mcompartida,envio);
	V(mutex_mem);
	V(mutex_mensaje);

	printf("Ingreso de datos de transaccion (con FIN finaliza):\n");
		
	do
	{
		do
		{
			fflush(stdin);
			printf("\tIngrese Moneda: ");
			scanf("%s",buf);
		}while(strcmp(buf,"FIN") != 0 && !verificar_moneda(atoi(buf)));
		
		if(strcmp(buf,"FIN") != 0)
		{
			ingreso.moneda = atoi(buf);
			
			do
			{
				fflush(stdin);
				printf("\tIngrese Cotizacion: ");
				scanf("%s",buf);
			}while(atoi(buf) <= 0);
			ingreso.cotizacion = atoi(buf);
			
			do
			{
				fflush(stdin);
				printf("\tIngrese Cantidad: ");
				scanf("%s",buf);
			}while(atoi(buf) <= 0);
			ingreso.cant_comprada = atoi(buf);
			
			sprintf(envio,"%d:%d:%d:%d\n",ingreso.moneda,ingreso.cotizacion,ingreso.cant_comprada,getpid());
		}		
			
		else		
		{
			flag_fin = 1;
			sprintf(envio,"FIN");
		}
			
		// Preparo envío
		P(mutex_atencion);
		P(mutex_mem);
		strcpy(mcompartida,envio);
		V(mutex_mem);
		V(mutex_mensaje);
		
		if(strcmp(buf,"FIN") != 0)
		{
			// Espero respuesta
			P(mutex_respuesta);
			P(mutex_mem);
			printf("<<< Monto a cobrar: %s >>>\n\n",mcompartida);
			V(mutex_mem);
			V(mutex_atencion);
		}
		
	}	while(flag_fin != 1);
	
	pause();
	return 0;
}

int verificar_moneda(int arg)
{
	if(arg > 0 && arg < CANT_MONEDAS)
		return 1;
	else
		return 0;
}

void abrir_semaforos()
{
	if((mutex_atencion = sem_open(atencion, 0)) == SEM_FAILED)
		error("No se puede abrir el semáforo");
	
	if((mutex_mensaje = sem_open(mensaje, 0)) == SEM_FAILED)
		error("No se puede abrir el semáforo");
	
	if((mutex_mem = sem_open(memoria, 0)) == SEM_FAILED)
		error("No se puede abrir el semáforo");
	
	if((mutex_respuesta = sem_open(respues, 0)) == SEM_FAILED)
		error("No se puede abrir el semáforo");
	
	if((mutex_inicio = sem_open(inicio, 0)) == SEM_FAILED)
		error("No se puede abrir el semáforo");
}

void cerrar_semaforos()
{
	sem_close(mutex_atencion);
	sem_close(mutex_mensaje);
	sem_close(mutex_mem);
	sem_close(mutex_respuesta);
	sem_close(mutex_inicio);
}

void handler(int signal)
{
	// Liberar memoria
	shmdt((char *)mcompartida);
	printf("\nServidor ha finalizado, terminando cliente...\n");
	cerrar_semaforos();
	exit(0);
}
